﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using MugenMvvmToolkit.Infrastructure;
using MugenMvvmToolkit.Interfaces;
using MugenMvvmToolkit.Models;
using MugenMvvmToolkit.Utils;
using MugenMvvmToolkit.ViewModels;
using MugenMvvmToolkitTest.TestInfrastructure;
using Should;

namespace MugenMvvmToolkitTest.ViewModel
{
    [TestClass]
    public class AsyncRelayCommandTest : RelayCommandTest
    {
        #region Test methods

        [TestMethod]
        public void AsyncCmdShouldExecuteInNewThread()
        {
            bool isInvoked = false;
            RelayCommand cmd = GetCommand(o => isInvoked = true, o => true);
            ThreadManager.ImmediateInvokeAsync = false;
            cmd.ThreadManager = ThreadManager;
            cmd.CanExecuteMode = ExecutionType.None;

            cmd.Execute(null);
            isInvoked.ShouldBeFalse();
            ThreadManager.InvokeAsyncAction.ShouldNotBeNull();
            ThreadManager.InvokeAsyncAction(ThreadManager.InvokeAsyncState);
            isInvoked.ShouldBeTrue();
        }

        [TestMethod]
        public void AsyncCmdShouldExecuteInNewThreadWithCallbackIfAny()
        {
            bool isInvoked = false;
            object calbackObj = null;
            Action<object> callback = o => { calbackObj = o; };

            var cmd = (AsyncRelayCommand)GetCommand(o => isInvoked = true, o => true);
            ThreadManager.ImmediateInvokeAsync = false;
            cmd.ThreadManager = ThreadManager;
            cmd.Callback = callback;
            cmd.CallbackExecutionMode = ExecutionType.SynchronousInUi;

            cmd.Execute(callback);
            isInvoked.ShouldBeFalse();
            ThreadManager.InvokeAsyncAction.ShouldNotBeNull();
            ThreadManager.InvokeAsyncAction(ThreadManager.InvokeAsyncState);
            isInvoked.ShouldBeTrue();

            calbackObj.ShouldBeNull();
            ThreadManager.InvokeInUiSynchronousAction();
            calbackObj.ShouldEqual(callback);
        }

        #endregion
        
        #region Overrides of RelayCommandTest

        protected override RelayCommand GetCommand(Action<object> execute, ExecutionType? executionMode = null,
                                                   IThreadManager threadManager = null)
        {
            GlobalSettings.DefaultThreadManager = ThreadManager;
            ThreadManager.ImmediateInvokeAsync = true;
            return new AsyncRelayCommand(execute, executionMode, threadManager);
        }

        protected override RelayCommand GetCommand(Action<object> execute, Predicate<object> canExecute,
                                                   params object[] notifiers)
        {
            GlobalSettings.DefaultThreadManager = ThreadManager;
            ThreadManager.ImmediateInvokeAsync = true;
            return new AsyncRelayCommand(execute, canExecute, notifiers);
        }

        protected override RelayCommand GetCommand(Action<object> execute, Predicate<object> canExecute,
                                                   ExecutionType? executionMode = null,
                                                   IThreadManager threadManager = null, params object[] notifiers)
        {
            GlobalSettings.DefaultThreadManager = ThreadManager;
            ThreadManager.ImmediateInvokeAsync = true;
            return new AsyncRelayCommand(execute, canExecute, executionMode, threadManager, notifiers);
        }

        #endregion
    }
}